﻿using RestApp.BusinessLogic.Abstract;
using RestApp.BusinessLogic.Code;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;

namespace RestApp.BusinessLogic
{
	public class UsersLogic : BaseLogic<User>, IUsersLogic
	{
		public override User GetById(object id)
		{
			using(var context = new RestAppEntities())
			{
				return context
					.Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
					.FirstOrDefault(t => t.Id == (int)id);
			}
		}

		public bool IsLoginExists(string login)
		{
			using(var context = new RestAppEntities())
			{
				return context
					.Users
					.Any(t => t.Login.ToUpper() == login.ToUpper());
			}
		}

		public override void Add(User item)
		{
			item.IsDelete = false;
			item.IsFired = false;
			base.Add(item);
		}

		public override IEnumerable<User> GetAll()
		{
			using(var context = new RestAppEntities())
			{
				return context
					.Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
					.Where(t => !t.IsFired && !t.IsDelete)
					.ToList();
			}
		}

		public IEnumerable<User> GetDeletedUsers()
		{
			using(var context = new RestAppEntities())
			{
				return context
					.Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
					.Where(t => t.IsDelete)
					.ToList();
			}
		}

		public override void RemoveById(object id)
		{
			using(var context = new RestAppEntities())
			{
				var user = context
					.Set<User>()
					.Find(id);
				user.IsDelete = true;
				context.SaveChanges();
			}
		}

        public IEnumerable<User> GetAllFired()
        {
            using(var context = new RestAppEntities())
            {
                return context
                    .Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
                    .Where(t => t.IsFired && !t.IsDelete)
                    .ToList();
            }
        }

        public bool VerifyUser(string login, string password)
        {
            using(var context = new RestAppEntities())
            {
                var user = context.Users.FirstOrDefault(t => t.Login.ToUpper() == login.ToUpper());
                if(user == null || user.IsDelete || user.IsFired)
                {
                    return false;
                }

                return user.Password == password;
            }
        }

        public string[] GetAllRoles()
        {
            using(var context = new RestAppEntities())
            {
                return context
                    .Roles
                    .Select(t => t.Name)
                    .ToArray();
            }
        }

        public string[] GetUserRoles(string login)
        {
            using(var context = new RestAppEntities())
            {
                var user = context
					.Users
					.FirstOrDefault(t => t.Login.ToUpper() == login.ToUpper());
                if(user == null)
                {
                    return new string[0];
                }
                return new string[] { user.Role.Name };
            }
        }

        public User GetByLogin(string login)
        {
            using(var context = new RestAppEntities())
            {
                return context
					.Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
                    .Include(t => t.JobTitle)
                    .Include(t => t.Role)
                    .FirstOrDefault(t => t.Login.ToUpper() == login.ToUpper());
            }
        }


        public IEnumerable<User> GetWorkingUsersOnDate(DateTime date, string loginFor)
        {
			if (string.IsNullOrEmpty(loginFor))
			{
				throw new ArgumentNullException("login");
			}

            using(var context = new RestAppEntities())
            {
				var user = context.Users.FirstOrDefault(t => t.Login.ToUpper() == loginFor.ToUpper());

				return context
					.WorkGraphics
					.Where(t => t.Year == date.Year
						&& t.Month == date.Month
						&& t.Day == date.Day)
					 .Select(t => t.User)
					 .Include(t => t.WorkGraphics)
					 .Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
					 .FilterUsersForCredentials(user);
            }
        }

		public IEnumerable<User> GetAllFilteredByLoginCredentials(string login)
		{
			if(string.IsNullOrEmpty(login))
			{
				throw new ArgumentNullException("login");
			}

			using(var context = new RestAppEntities())
			{
				var user = context.Users.FirstOrDefault(t => t.Login.ToUpper() == login.ToUpper());
				if(user == null)
				{
					throw new InvalidOperationException("user with login " + login + " doesn't exists in database");
				}
				return context
					.Users
					.Include(t => t.WorkGraphics)
					.Include(t => t.WorkGraphics.Select(q => q.FactOfWorks))
					.FilterUsersForCredentials(user);
			}
		}
	}
}
